#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""检测器管理器

统一管理不同类型的检测引擎，实现模型的动态加载、切换和性能监控
"""

import logging
import time
import threading
from typing import Dict, Optional, List, Any, Tuple
import numpy as np

from core.detection.base_engine import BaseDetectionEngine
from core.detection.yolo_engine import YOLODetectionEngine
from core.detection.yolo_tracking_engine import YOLOTrackingEngine


class MockDetectionEngine(BaseDetectionEngine):
    """模拟检测引擎，用于测试环境，不依赖实际模型文件"""
    
    def __init__(self, model_path=None, device='cpu', **kwargs):
        """初始化模拟检测引擎"""
        self.model_path = model_path or "mock_model.pt"
        self.device = device
        self.confidence_threshold = kwargs.get('confidence_threshold', 0.5)
        self._performance_metrics = {
            'inference_time': 0.01,
            'fps': 100,
            'memory_usage': 0.1
        }
        self._is_healthy = True
        logging.info("MockDetectionEngine初始化完成")
    
    def initialize(self):
        """初始化引擎，BaseDetectionEngine抽象方法的实现"""
        logging.info("MockDetectionEngine初始化中...")
        # 模拟初始化过程
        # 在实际引擎中，这里会加载模型、设置设备等
        self._is_healthy = True
        logging.info("MockDetectionEngine初始化完成")
        return True
    
    def detect(self, image, **kwargs):
        """模拟检测，返回固定的检测结果"""
        # 生成一些模拟的检测结果
        confidence = kwargs.get('confidence_threshold', self.confidence_threshold)
        results = [
            {
                'class_id': 0,
                'class_name': 'person',
                'confidence': 0.95,
                'bbox': [100, 100, 200, 300]  # [x1, y1, x2, y2]
            },
            {
                'class_id': 2,
                'class_name': 'car',
                'confidence': 0.85,
                'bbox': [300, 200, 500, 350]
            }
        ]
        # 过滤低置信度结果
        return [r for r in results if r['confidence'] >= confidence]
    
    def batch_detect(self, images, **kwargs):
        """模拟批量检测"""
        return [self.detect(image, **kwargs) for image in images]
    
    def get_performance_metrics(self):
        """返回性能指标"""
        return self._performance_metrics.copy()
    
    def update_config(self, **kwargs):
        """更新配置"""
        for key, value in kwargs.items():
            if hasattr(self, key):
                setattr(self, key, value)
        return True
    
    def get_model_info(self):
        """获取模型信息，DetectorManager.list_engines()方法需要调用此方法"""
        return {
            'model_path': self.model_path,
            'device': self.device,
            'type': 'mock',
            'confidence_threshold': self.confidence_threshold
        }
    
    def is_healthy(self):
        """检查引擎是否健康，DetectorManager.list_engines()方法需要调用此方法"""
        return self._is_healthy
    
    def release(self):
        """释放引擎资源，DetectorManager.remove_engine()方法需要调用此方法"""
        self._is_healthy = False
        logging.info("MockDetectionEngine资源已释放")
    
    def optimize_for_realtime(self, **kwargs):
        """模拟性能优化，DetectorManager.optimize_performance()方法可能调用此方法"""
        # 更新性能指标
        self._performance_metrics['fps'] *= 1.5
        self._performance_metrics['inference_time'] /= 1.5
        logging.info("MockDetectionEngine性能已优化")
        return True
# 导入根目录下的config.py文件，避免与config包冲突
import sys
import os
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))))
# 使用importlib动态导入根目录下的config.py
import importlib.util
spec = importlib.util.spec_from_file_location("root_config", os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))), "config.py"))
root_config = importlib.util.module_from_spec(spec)
spec.loader.exec_module(root_config)
# 从动态导入的模块中获取函数
get_config = root_config.get_config
get_all_configs = root_config.get_all_configs

# 设置日志记录器
logger = logging.getLogger(__name__)

class DetectorManager:
    """检测器管理器
    
    统一管理不同类型的检测引擎，实现模型的动态加载、切换和性能监控
    """
    
    def __init__(self):
        """初始化检测器管理器"""
        # 获取配置
        self.config = get_all_configs()
        
        # 检测引擎实例字典
        self._engines: Dict[str, BaseDetectionEngine] = {}
        
        # 当前活动引擎
        self._active_engine: Optional[BaseDetectionEngine] = None
        
        # 模型加载状态
        self._loading_status: Dict[str, bool] = {}
        
        # 线程锁，确保线程安全
        self._lock = threading.RLock()
        
        # 性能监控缓存
        self._performance_history: Dict[str, List[Dict[str, Any]]] = {}
        self._max_history_size = 100  # 性能历史最大记录数
        
        logger.info("DetectorManager初始化完成")
    
    def create_engine(self, engine_id: str, engine_type: str = 'yolo', 
                     model_path: Optional[str] = None, device: str = 'auto', 
                     **kwargs) -> BaseDetectionEngine:
        """创建一个新的检测引擎实例
        
        Args:
            engine_id: 引擎唯一标识符
            engine_type: 引擎类型，'yolo'（普通YOLO检测）或'yolo_tracking'（带跟踪功能）
            model_path: 模型文件路径
            device: 运行设备，'auto'、'cuda'、'cpu'
            **kwargs: 引擎配置参数
            
        Returns:
            BaseDetectionEngine: 创建的检测引擎实例
            
        Raises:
            ValueError: 如果引擎类型不支持或ID已存在
        """
        with self._lock:
            # 检查ID是否已存在
            if engine_id in self._engines:
                logger.warning(f"引擎ID '{engine_id}' 已存在，返回现有引擎")
                return self._engines[engine_id]
            
            # 记录加载状态
            self._loading_status[engine_id] = True
            
            try:
                # 创建引擎实例
                if engine_type == 'mock':
                    # 创建模拟引擎，用于测试环境
                    engine = MockDetectionEngine(
                        model_path=model_path,
                        device=device,
                        **kwargs
                    )
                elif engine_type == 'yolo':
                    engine = YOLODetectionEngine(
                        model_path=model_path,
                        device=device,
                        **kwargs
                    )
                elif engine_type == 'yolo_tracking':
                    engine = YOLOTrackingEngine(
                        model_path=model_path,
                        device=device,
                        **kwargs
                    )
                else:
                    raise ValueError(f"不支持的引擎类型: {engine_type}")
                
                # 保存引擎实例
                self._engines[engine_id] = engine
                
                # 如果是第一个引擎，自动设为活动引擎
                if self._active_engine is None:
                    self._active_engine = engine
                
                # 初始化性能历史
                self._performance_history[engine_id] = []
                
                logger.info(f"成功创建检测引擎: {engine_id} (类型: {engine_type})")
                
                return engine
                
            except Exception as e:
                logger.error(f"创建引擎 '{engine_id}' 失败: {str(e)}")
                raise
            finally:
                # 更新加载状态
                self._loading_status[engine_id] = False
    
    def get_engine(self, engine_id: str) -> Optional[BaseDetectionEngine]:
        """获取指定ID的检测引擎
        
        Args:
            engine_id: 引擎唯一标识符
            
        Returns:
            BaseDetectionEngine or None: 检测引擎实例或None（如果不存在）
        """
        with self._lock:
            return self._engines.get(engine_id)
    
    def set_active_engine(self, engine_id: str) -> bool:
        """设置活动的检测引擎
        
        Args:
            engine_id: 引擎唯一标识符
            
        Returns:
            bool: 是否设置成功
        """
        with self._lock:
            if engine_id in self._engines:
                self._active_engine = self._engines[engine_id]
                logger.info(f"已切换到活动引擎: {engine_id}")
                return True
            else:
                logger.error(f"引擎 '{engine_id}' 不存在")
                return False
    
    def get_active_engine(self) -> Optional[BaseDetectionEngine]:
        """获取当前活动的检测引擎
        
        Returns:
            BaseDetectionEngine or None: 当前活动的检测引擎或None（如果没有）
        """
        with self._lock:
            return self._active_engine
    
    def list_engines(self) -> List[Dict[str, Any]]:
        """列出所有已创建的检测引擎
        
        Returns:
            List[Dict]: 引擎信息列表
        """
        with self._lock:
            engine_list = []
            for engine_id, engine in self._engines.items():
                # 获取引擎基本信息
                engine_info = {
                    'engine_id': engine_id,
                    'type': engine.__class__.__name__,
                    'active': engine is self._active_engine,
                    'loading': self._loading_status.get(engine_id, False),
                    'model_path': engine.get_model_info().get('model_path', 'unknown'),
                    'device': engine.get_model_info().get('device', 'unknown'),
                    'status': 'running' if engine.is_healthy() else 'error'
                }
                
                # 尝试获取更详细的信息
                try:
                    engine_info['model_info'] = engine.get_model_info()
                    engine_info['performance'] = engine.get_performance_metrics()
                except Exception as e:
                    logger.warning(f"获取引擎 '{engine_id}' 详细信息失败: {str(e)}")
                
                engine_list.append(engine_info)
            
            return engine_list
    
    def remove_engine(self, engine_id: str) -> bool:
        """移除指定的检测引擎
        
        Args:
            engine_id: 引擎唯一标识符
            
        Returns:
            bool: 是否移除成功
        """
        with self._lock:
            if engine_id in self._engines:
                # 释放引擎资源
                engine = self._engines[engine_id]
                engine.release()
                
                # 删除引擎实例
                del self._engines[engine_id]
                
                # 如果是当前活动引擎，切换到其他引擎
                if self._active_engine == engine:
                    self._active_engine = next(iter(self._engines.values()), None)
                    logger.info(f"活动引擎 '{engine_id}' 已移除，已切换到新的活动引擎")
                
                # 删除相关记录
                if engine_id in self._loading_status:
                    del self._loading_status[engine_id]
                
                if engine_id in self._performance_history:
                    del self._performance_history[engine_id]
                
                logger.info(f"已移除检测引擎: {engine_id}")
                return True
            else:
                logger.error(f"引擎 '{engine_id}' 不存在")
                return False
    
    def detect(self, image: Any, **kwargs) -> List[Dict[str, Any]]:
        """使用当前活动引擎执行检测
        
        Args:
            image: 输入图像（numpy数组或文件路径）
            **kwargs: 检测参数
            
        Returns:
            List[Dict]: 检测结果列表
            
        Raises:
            ValueError: 如果没有活动的检测引擎
        """
        if self._active_engine is None:
            raise ValueError("没有活动的检测引擎")
        
        start_time = time.time()
        try:
            result = self._active_engine.detect(image, **kwargs)
            
            # 更新性能历史
            engine_id = self._get_engine_id_by_instance(self._active_engine)
            if engine_id:
                metrics = self._active_engine.get_performance_metrics()
                metrics['detect_time'] = time.time() - start_time
                self._update_performance_history(engine_id, metrics)
            
            return result
        except Exception as e:
            logger.error(f"检测失败: {str(e)}")
            raise
    
    def batch_detect(self, images: List[Any], **kwargs) -> List[List[Dict[str, Any]]]:
        """批量检测
        
        Args:
            images: 图像列表
            **kwargs: 检测参数
            
        Returns:
            List[List[Dict]]: 检测结果列表
            
        Raises:
            ValueError: 如果没有活动的检测引擎
        """
        if self._active_engine is None:
            raise ValueError("没有活动的检测引擎")
        
        start_time = time.time()
        try:
            result = self._active_engine.batch_detect(images, **kwargs)
            
            # 更新性能历史
            engine_id = self._get_engine_id_by_instance(self._active_engine)
            if engine_id:
                metrics = self._active_engine.get_performance_metrics()
                metrics['batch_detect_time'] = time.time() - start_time
                metrics['images_processed'] = len(images)
                self._update_performance_history(engine_id, metrics)
            
            return result
        except Exception as e:
            logger.error(f"批量检测失败: {str(e)}")
            raise
    
    def track(self, image: Any, **kwargs) -> List[Dict[str, Any]]:
        """使用当前活动引擎执行跟踪（如果支持）
        
        Args:
            image: 输入图像
            **kwargs: 跟踪参数
            
        Returns:
            List[Dict]: 跟踪结果列表
            
        Raises:
            ValueError: 如果没有活动的检测引擎或不支持跟踪功能
        """
        if self._active_engine is None:
            raise ValueError("没有活动的检测引擎")
        
        # 检查引擎是否支持跟踪
        if not hasattr(self._active_engine, 'track'):
            raise ValueError("当前活动引擎不支持跟踪功能")
        
        start_time = time.time()
        try:
            # 先执行检测
            detections = self._active_engine.detect(image, **kwargs)
            
            # 再执行跟踪
            result = self._active_engine.track(detections, image)
            
            # 更新性能历史
            engine_id = self._get_engine_id_by_instance(self._active_engine)
            if engine_id:
                metrics = self._active_engine.get_performance_metrics()
                metrics['track_time'] = time.time() - start_time
                self._update_performance_history(engine_id, metrics)
            
            return result
        except Exception as e:
            logger.error(f"跟踪失败: {str(e)}")
            raise
    
    def optimize_performance(self, engine_id: Optional[str] = None, **kwargs):
        """优化检测引擎性能
        
        Args:
            engine_id: 引擎ID，None表示当前活动引擎
            **kwargs: 优化参数
        """
        with self._lock:
            if engine_id is not None:
                engine = self._engines.get(engine_id)
            else:
                engine = self._active_engine
            
            if engine is None:
                raise ValueError("指定的检测引擎不存在")
            
            try:
                # 调用引擎的优化方法
                if hasattr(engine, 'optimize_for_realtime'):
                    engine.optimize_for_realtime(**kwargs)
                    logger.info(f"已优化引擎 '{engine_id or 'active'}' 性能")
                else:
                    logger.warning(f"引擎 '{engine_id or 'active'}' 不支持性能优化")
            except Exception as e:
                logger.error(f"优化引擎性能失败: {str(e)}")
                raise
    
    def get_performance_history(self, engine_id: Optional[str] = None) -> List[Dict[str, Any]]:
        """获取性能历史记录
        
        Args:
            engine_id: 引擎ID，None表示当前活动引擎
            
        Returns:
            List[Dict]: 性能历史记录
        """
        with self._lock:
            if engine_id is None and self._active_engine is not None:
                engine_id = self._get_engine_id_by_instance(self._active_engine)
            
            if engine_id in self._performance_history:
                return self._performance_history[engine_id].copy()
            else:
                return []
    
    def reset_all_engines(self):
        """重置所有检测引擎"""
        with self._lock:
            # 释放所有引擎资源
            for engine in self._engines.values():
                engine.release()
            
            # 清空所有记录
            self._engines.clear()
            self._active_engine = None
            self._loading_status.clear()
            self._performance_history.clear()
            
            logger.info("所有检测引擎已重置")
    
    def _get_engine_id_by_instance(self, engine: BaseDetectionEngine) -> Optional[str]:
        """根据引擎实例获取引擎ID
        
        Args:
            engine: 引擎实例
            
        Returns:
            str or None: 引擎ID或None
        """
        for engine_id, engine_instance in self._engines.items():
            if engine_instance is engine:
                return engine_id
        return None
    
    def _update_performance_history(self, engine_id: str, metrics: Dict[str, Any]):
        """更新性能历史记录
        
        Args:
            engine_id: 引擎ID
            metrics: 性能指标
        """
        if engine_id in self._performance_history:
            history = self._performance_history[engine_id]
            history.append(metrics)
            
            # 限制历史记录数量
            if len(history) > self._max_history_size:
                self._performance_history[engine_id] = history[-self._max_history_size:]

# 创建全局检测器管理器实例
global_detector_manager = DetectorManager()

def get_detector_manager() -> DetectorManager:
    """获取全局检测器管理器实例
    
    Returns:
        DetectorManager: 全局检测器管理器实例
    """
    return global_detector_manager